//
//  CircleView.m
//  BeautyBaoUnion
//
//  Created by 肖智 on 2016/10/24.
//  Copyright © 2016年 肖智. All rights reserved.
//

#import "CircleView.h"

@interface CircleView(){
    unsigned char *_imageData;
    UIColor *_currentColor;
    CGPoint _center;
    UIColor *_strokeColor;
    CGFloat _startAngle;
    CGFloat _endAngle;
    CGFloat _radius;
    
    //动画时间
    CGFloat _duration;
    //角度相关
    CGFloat _averageAngle;
    //采样频率
    NSInteger _maxCount;
    NSInteger _currentCount;
    //显示数值
    NSInteger _maxValue;
    NSInteger _currentMaxValue;
    NSInteger _averageValue;

    NSInteger _currentValue;
    
    NSMutableArray *_labelArray;
    
}
@property(nonatomic,strong)CAShapeLayer *circleLayer;
@property(nonatomic,strong)CADisplayLink *timer;
@property(nonatomic,strong)UIImageView *shapeImageView;
@property(nonatomic,strong)UIImageView *ybImageView;
@property(nonatomic,strong)UILabel *valueLabel;
@property(nonatomic,strong)UIButton *detailsButton;
@end
@implementation CircleView
- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        _labelArray = [[NSMutableArray alloc] initWithCapacity:0];
        [self addSubview:self.shapeImageView];
        [self.layer addSublayer:self.circleLayer];
        [self addSubview:self.ybImageView];
        
        _imageData = [self genDataWithImage:self.shapeImageView.image.CGImage];
        [self defautSettings];
        [self addSubview:self.valueLabel];
        [self addSubview:self.detailsButton];
        
        //调整yb位置
        self.ybImageView.transform = CGAffineTransformMakeRotation(M_PI_2+_startAngle);
        self.ybImageView.center = [self getPointWithAngle:_startAngle];
//        self.backgroundColor = [UIColor lightGrayColor];

    }
    return self;
}
- (void)defautSettings{
    _radius = self.shapeImageView.bounds.size.width/2.0-4;
    _center = CGPointMake(self.shapeImageView.bounds.size.width/2.0, 125);
    _strokeColor = [UIColor cyanColor];
    CGFloat angle = acosf(116/125.0);
    _startAngle = M_PI-angle;
    _endAngle = angle;
    _duration = 1.4;
    _maxValue = 2000;
//    NSLog(@"startPoint:%@,endPoint:%@",NSStringFromCGPoint([self getPointWithAngle:_startAngle]), NSStringFromCGPoint([self getPointWithAngle:_endAngle]));
//    UIBezierPath *path =  [UIBezierPath bezierPath];
//    [path addArcWithCenter:_center radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
//    [self setStrokeColor:[UIColor redColor]];
//    self.circleLayer.path = path.CGPath;
//    CABasicAnimation *pathAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
//    pathAnima.duration = 3.0f;
//    pathAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//    pathAnima.fromValue = [NSNumber numberWithFloat:0.0f];
//    pathAnima.toValue = [NSNumber numberWithFloat:1.0f];
//    pathAnima.fillMode = kCAFillModeForwards;
//    pathAnima.removedOnCompletion = NO;
//    [_circleLayer addAnimation:pathAnima forKey:@"strokeEndAnimation"];
//    [self adjustYoubiaoWithAngle:_endAngle];
    
}
- (void)layoutWithLevelValueArray:(NSArray *)levelArray{
    if(levelArray.count==0){
        return;
    }
    for(UILabel *lbl in _labelArray){
        if(lbl){
            [lbl removeFromSuperview];
        }
    }
    NSInteger total = levelArray.count;
    CGFloat average = (M_PI+2*_endAngle)/(total-1);
    CGFloat currentAngle;
    UILabel *label;
    for(NSInteger i=0;i<total;i++){
        currentAngle = _startAngle+average*i;
        CGPoint pt = CGPointZero;
        CGFloat radius = _radius-15;
        pt.x = _center.x+round(radius*cosf(currentAngle));
        pt.y = _center.y+round(radius*sinf(currentAngle));
        label = [[UILabel alloc] init];
        label.frame = CGRectMake(0, 0, 60, 20);
        label.font = [UIFont systemFontOfSize:11];
        label.textAlignment = NSTextAlignmentCenter;
        label.textColor = [UIColor colorWithHex:0x8d8d8d alpha:1.0];
        label.text = (NSString *)levelArray[i];
        label.transform = CGAffineTransformMakeRotation(M_PI_2+currentAngle);
        label.center = pt;
        [self addSubview:label];
    }
}
- (void)setPercent:(CGFloat)percent{
    _maxCount = _duration*60;
    _averageAngle = (M_PI+2*_endAngle)*percent/_maxCount;
    _currentCount = 0;
    
    _currentMaxValue = _maxValue*percent;
    _currentValue = 0;
    _averageValue = _currentMaxValue/_maxCount;
    
    _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNextPosition:)];
    _timer.paused = NO;
    [_timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)setNextPosition:(CADisplayLink *)displayLink{
    if(_currentCount>_maxCount){
        _valueLabel.text = [NSString stringWithFormat:@"%ld",_currentMaxValue];
        _timer.paused = YES;
        [_timer invalidate];
        _timer = nil;
        return;
    }
    CGFloat currentAngle = _startAngle+_currentCount*_averageAngle;
    if (currentAngle>M_PI*2+_endAngle){
        currentAngle = M_PI*2+_endAngle;
    }
    [self updateViewsWithAngle:currentAngle];
    _currentCount++;
//    NSLog(@"currentPoint:%@",NSStringFromCGPoint([self getPointWithAngle:currentAngle]));

}
- (void)updateViewsWithAngle:(CGFloat)angle{
    CGPoint pt = [self getPointWithAngle:angle];
    UIColor *currentColor = [self getColorAtPoint:pt];
    self.ybImageView.transform = CGAffineTransformMakeRotation(M_PI_2+angle);
    self.ybImageView.center = pt;
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:_center radius:_radius startAngle:_startAngle endAngle:angle clockwise:YES];
    _circleLayer.path = path.CGPath;
    [self setStrokeColor:currentColor];
    
    _currentValue = _currentCount*_averageValue;
    _valueLabel.text = [NSString stringWithFormat:@"%ld",_currentValue];
    _valueLabel.textColor = currentColor;
    _detailsButton.backgroundColor = currentColor;
}
- (CGPoint)getPointWithAngle:(CGFloat)angle{
    CGPoint pt = CGPointZero;
    pt.x = _center.x+round(_radius*cosf(angle));
    pt.y = _center.y+round(_radius*sinf(angle));
    return pt;
}
#pragma mark setter/getter
- (void)setStrokeColor:(UIColor *)strokeColor{
    _strokeColor = strokeColor;
    _circleLayer.strokeColor = strokeColor.CGColor;
}

- (void)setDuration:(CGFloat)duration{
    _duration = duration;
}
- (void)setMaxValue:(NSInteger)value{
    _maxValue = value;
}
#pragma mark image data
- (UIColor *)getColorAtPoint:(CGPoint)aPoint{
    CGFloat scale = [[UIScreen mainScreen] scale];
    size_t w = CGImageGetWidth(self.shapeImageView.image.CGImage);
    size_t h = CGImageGetHeight(self.shapeImageView.image.CGImage);
    UIColor *color = nil;
    if (_imageData != NULL) {
        //offset locates the pixel in the data from x,y.
        //4 for 4 bytes of data per pixel, w is width of one row of data.
        int offset = 4*((w*round(aPoint.y)*scale)+round(aPoint.x)*scale);
        int alpha =  _imageData[offset];
        int red = _imageData[offset+1];
        int green = _imageData[offset+2];
        int blue = _imageData[offset+3];
        color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
    }
    return color;
}
- (unsigned char *)genDataWithImage:(CGImageRef)dstImage{
    CGContextRef ctx = [self createARGBBitmapContextFromImage:dstImage];
    if (ctx == NULL) { return nil; /* error */ }
    
    size_t w = CGImageGetWidth(dstImage);
    size_t h = CGImageGetHeight(dstImage);
    CGRect rect = {{0,0},{w,h}};
    
    
    // Draw the image to the bitmap context. Once we draw, the memory
    // allocated for the context for rendering will then contain the
    // raw image data in the specified color space.
    CGContextDrawImage(ctx, rect, dstImage);
    
    // Now we can get a pointer to the image data associated with the bitmap
    // context.
    unsigned char* data = CGBitmapContextGetData(ctx);
    return data;
}
- (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage
{
    CGContextRef context = NULL;
    CGColorSpaceRef colorSpace;
    void *bitmapData;
    long bitmapByteCount;
    long bitmapBytesPerRow;
    
    // Get image width, height. We'll use the entire image.
    size_t pixelsWide = CGImageGetWidth(inImage);
    size_t pixelsHigh = CGImageGetHeight(inImage);
    
    // Declare the number of bytes per row. Each pixel in the bitmap in this
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and
    // alpha.
    bitmapBytesPerRow   = (pixelsWide * 4);
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);
    
    // Use the generic RGB color space.
    colorSpace = CGColorSpaceCreateDeviceRGB();
    
    if (colorSpace == NULL)
    {
        fprintf(stderr,"Error allocating color space\n");
        return NULL;
    }
    
    // Allocate memory for image data. This is the destination in memory
    // where any drawing to the bitmap context will be rendered.
    bitmapData = malloc(bitmapByteCount);
    if (bitmapData == NULL)
    {
        fprintf(stderr,"Memory not allocated!");
        CGColorSpaceRelease(colorSpace);
        return NULL;
    }
    
    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
    // per component. Regardless of what the source image format is
    // (CMYK, Grayscale, and so on) it will be converted over to the format
    // specified here by CGBitmapContextCreate.
    context = CGBitmapContextCreate(bitmapData,
                                    pixelsWide,
                                    pixelsHigh,
                                    8,   // bits per component
                                    bitmapBytesPerRow,
                                    colorSpace,
                                    kCGImageAlphaPremultipliedFirst);
    if (context == NULL)
    {
        free(bitmapData);
        fprintf(stderr,"Context not created!");
    }
    
    // Make sure and release colorspace before returning
    CGColorSpaceRelease(colorSpace);
    return context;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
#pragma mark --lazy load
- (CAShapeLayer *)circleLayer{
    if(!_circleLayer){
        _circleLayer = [[CAShapeLayer alloc] init];
        _circleLayer.frame = self.bounds;
        _circleLayer.lineJoin = kCALineJoinBevel;
        _circleLayer.lineCap = kCALineJoinBevel;
        _circleLayer.fillColor = [UIColor clearColor].CGColor;
        _circleLayer.lineWidth = 8;
    }
    return _circleLayer;
}
- (UIImageView *)shapeImageView{
    if(!_shapeImageView){
        _shapeImageView = [[UIImageView alloc] init];
        _shapeImageView.frame = self.bounds;
        _shapeImageView.image = [UIImage imageNamed:@"circle_bg"];
    }
    return _shapeImageView;
}
- (UIImageView *)ybImageView{
    if(!_ybImageView){
        _ybImageView = [[UIImageView alloc] init];
        _ybImageView.frame = CGRectMake(0, 0, 10, 13);
        _ybImageView.image = [UIImage imageNamed:@"youbiao"];
    }
    return _ybImageView;
}
- (UILabel *)valueLabel{
    if(!_valueLabel){
        _valueLabel = [[UILabel alloc] init];
        _valueLabel.frame = CGRectMake(0, 0, 80, 30);
        _valueLabel.font = [UIFont systemFontOfSize:28];
        _valueLabel.textAlignment = NSTextAlignmentCenter;
        _valueLabel.text = @"800";
        _valueLabel.center = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0);
    }
    return _valueLabel;
}
- (UIButton *)detailsButton{
    if(!_detailsButton){
        _detailsButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _detailsButton.frame = CGRectMake(0, 0, 80, 30);
        [_detailsButton setTitle:@"分值解读" forState:UIControlStateNormal];
        [_detailsButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        _detailsButton.titleLabel.font = [UIFont systemFontOfSize:15];
        _detailsButton.center = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0+40);
    }
    return _detailsButton;
}
- (void)dealloc{
    if(_imageData!=NULL){
        free(_imageData);
    }
    [_timer setPaused:YES];
    [_timer invalidate];
    _timer = nil;
}
@end
